# -*- coding: utf-8 -*-
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import *
import json, time
import redis
import re
import logging
import logging.handlers
import sys
from alert.app import *
from config.tdm_config import *
from acard.acard_utils import *
from datetime import datetime, date
import config.tdm_mongo_modules as tmm

reload(sys)
sys.setdefaultencoding('utf8')

SERVER_POST_DEBUG = False
NETWORK_POST_DEBUG = False
MDM_POST_DEBUG = False
ACARD_POST_DEBUG = True
COMMON_DEBUG = False

def city_exist_check(r, req_city):
    if COMMON_DEBUG:
        print 'city_exist_check', req_city
    if req_city == None or req_city == '' or req_city.find('_') >= 0 or req_city.find(':') >= 0:
        return False
    if not req_city in r.hkeys(tdm_redis_key_jxd):
        return False
    return True

def jxd_exist_check(r, req_city, req_jxd):
    if COMMON_DEBUG:
        print 'jxd_exist_check', req_city, req_jxd
    if req_jxd == None or req_jxd == '' or req_jxd.find('_') >= 0 or req_jxd.find(':') >= 0:
        return False
    jxd_str = r.hget(tdm_redis_key_jxd, req_city)
    jxd_list = jxd_str and jxd_str.split(',') or []
    if not req_jxd in jxd_list:
        return False
    return True

def macaddr_check(macaddr):
    re_str = r'^[a-zA-Z0-9]{2}-[a-zA-Z0-9]{2}-[a-zA-Z0-9]{2}-[a-zA-Z0-9]{2}-[a-zA-Z0-9]{2}-[a-zA-Z0-9]{2}$'
    if re.match(re_str, macaddr):
        return True
    return False

def battery_check(battery):
    if not battery or int(battery) < 0 or int(battery) > 100:
        return False
    return True

def server_exist_check(r, req_city, req_jxd, req_server):
    if SERVER_POST_DEBUG:
        print 'server_exist_check', req_city, req_jxd, req_server
    if req_server == None or req_server == '' or req_server.find('_') > 0 or req_server.find(':') > 0:
        return False
    server_key = '%s:%s:%s' % (req_city, req_jxd, req_server)
    return r.hexists(tdm_redis_key_server, server_key)

def get_city_jxd_by_server(r, server):
    city = ''
    jxd = ''
    found_server = False
    for city_jxd_serv in r.hkeys(tdm_redis_key_server):
        city, jxd, serv = city_jxd_serv.split(':')
        if server == serv:
            found_server = True
            break
    if found_server:
        return city, jxd

    return '', ''

def server_post_to_redis(r, request, city, jxd, server, item_re_list):
    #print 'server_post_to_redis'
    ret = {}

    #get the time of sec
    cur_time = int(time.time()*1000)
    if SERVER_POST_DEBUG:
        print "cur_time is", cur_time

    #get the itemlist
    for req_post_key in request.POST.keys():
        req_post_key = req_post_key.encode('utf-8')
        for re_str, re_func in tdm_server_items_re_list:

            #match the regex
            if re.match(re_str, req_post_key):
                #get the val
                val = request.POST.get(req_post_key)
                if SERVER_POST_DEBUG:
                    print "%s=%s" % (req_post_key, val)

                #save data to redis
                db_hash_name = "%s:%s:%s:%s:%s" % (tdm_redis_key_server_item_prefix, city, jxd, server, req_post_key)

                db_hash_key = "%s" % (cur_time)
                r.hset(db_hash_name, db_hash_key, val)                
                ret[req_post_key] = val

                #server check the warning/alert
                server_item_warning_alert_check(r, city, jxd, server, req_post_key, cur_time, val, re_func)
    #print ret
    ret['result'] = 1
    return ret

def _server_post(request):
    ret = {}
    ret['result'] = 0

    if SERVER_POST_DEBUG:
        print request.POST

    #logging.basicConfig(level=logging.INFO,
    #    format='%(asctime)s %(levelname)s %(message)s',
    #    filename='post.log',
    #    filemode='a')

    #connect the redis database
    r = redis.Redis(host=tdm_redis_host, db=tdm_redis_db)

    #city = request.POST.get('city', '').encode('utf-8')
    #jxd = request.POST.get('school').encode('utf-8')
    server = request.POST.get('hostname', '').encode('utf-8')
    client_addr = request.META.get('REMOTE_ADDR', '')
    city, jxd = get_city_jxd_by_server(r, server)

    if SERVER_POST_DEBUG:
        print "%s=%s" % ("city", city)
        print "%s=%s" % ("jxd", jxd)
        print "%s=%s" % ("server", server)
        print "%s=%s" % ("client_addr", client_addr)

    #check city is valiable
    if city_exist_check(r, city) == False:
        err_msg = '(%s)%s city "%s" is incorrect' % (server, client_addr, city)
        print err_msg
        #logging.error(err_msg)
        ret['err_msg'] = err_msg
        return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

    #check school is valiable
    if jxd_exist_check(r, city, jxd) == False:
        err_msg = "(%s)%s school '%s' is incorrect" % (server, client_addr, jxd)
        print err_msg
        #logging.error(err_msg)
        ret['err_msg'] = err_msg
        return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

    #check server is valiable
    if server_exist_check(r, city, jxd, server) == False:
        err_msg = "(%s)%s hostname '%s' is incorrect" % (server, client_addr, server)
        print err_msg
        #logging.error(err_msg)
        ret['err_msg'] = err_msg
        return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

    ret.update({'city': city})
    ret.update({'jxd': jxd})
    ret.update({'server': server})

    try:
        ret = server_post_to_redis(r, request, city, jxd, server, tdm_server_items_re_list)
        #logging.info("(%s)%s post is ok" % (server, client_addr))
        print "(%s)%s post is ok" % (server, client_addr)
    except Exception as e:
        err_msg = "(%s)%s error: %s" % (server, client_addr, str(e))
        #logging.error(err_msg)
        print err_msg
        ret['err_msg'] = err_msg
        return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

    return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

def server_post(request):
    try:
        return _server_post(request)
    except Exception as e:
        err_msg = '(server error):%s' % str(e)
        print err_msg
        return HttpResponseServerError(err_msg)


def network_post_to_redis(r, request):
    cur_time = int(time.time()*1000)
    if NETWORK_POST_DEBUG:
        print "cur_time is", cur_time

    for city_jxd_dev_item in request.POST.keys():

        val = request.POST.get(city_jxd_dev_item, '').encode('utf-8')
        city_jxd_dev_item = city_jxd_dev_item.encode('utf-8')

        if NETWORK_POST_DEBUG:
            print city_jxd_dev_item, val

        for re_str, re_func in tdm_network_items_re_list:
            net_re = re.match(re_str, city_jxd_dev_item)
            if not net_re:
                err_msg = "'%s' is incorrect" % (city_jxd_dev_item)
                print err_msg
                #logging.error(err_msg)
                continue
                #ret['err_msg'] = err_msg
                #return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

            city_jxd_dev, item = net_re.groups()
            if city_jxd_dev in r.hkeys(tdm_redis_key_network):
                db_hash_name = "%s:%s:%s" % (tdm_redis_key_network_item_prefix, city_jxd_dev, item)
                db_hash_key = "%s" % (cur_time)
                r.hset(db_hash_name, db_hash_key, val)
                #ret[city_jxd_dev_item] = val

                #server check the warning/alert
                network_item_warning_alert_check(r, city_jxd_dev, item, cur_time, val, re_func)
            else:
                err_msg = '"%s" is incorrect' % (city_jxd_dev)
                print err_msg
                #logging.error(err_msg)
                continue
                #print err_msg
                #ret['err_msg'] = err_msg
                #return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

    #network jxd alert online check
    network_jxd_alert_check(r, cur_time, 'online')

def _network_post(request):
    ret = {}
    ret['result'] = 0

    if NETWORK_POST_DEBUG:
        print request.POST

    #logging.basicConfig(level=logging.INFO,
    #    format='%(asctime)s %(levelname)s %(message)s',
    #    filename='post.log',
    #    filemode='a')

    #connect the redis database
    r = redis.Redis(host=tdm_redis_host, db=tdm_redis_db)

    client_addr = request.META.get('REMOTE_ADDR', '')
    if NETWORK_POST_DEBUG:
        print "%s=%s" % ("client_addr", client_addr)

    try:
        network_post_to_redis(r, request)
        print "%s post is ok" % (client_addr, )
        #logging.info("%s post is ok" % (client_addr, ))
        ret['result'] = 1
    except Exception as e:
        err_msg = "%s post error: %s" % (client_addr, str(e))
        #logging.error(err_msg)
        ret['err_msg'] = err_msg
        print err_msg
        return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

    if NETWORK_POST_DEBUG:
        print "done"
    return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

def network_post(request):
    try:
        return _network_post(request)
    except Exception as e:
        err_msg = '(network error):%s' % str(e)
        print err_msg
        return HttpResponseServerError(err_msg)


def power_post(request):
    pass


def mdm_post_to_redis(r, request, ipaddr, city, jxd, classroom):
    cur_time = int(time.time()*1000)
    if MDM_POST_DEBUG:
        print "cur_time is", cur_time

    macaddr = request.POST.get('macaddr', '').encode('utf-8').replace(':', '-')
    battery = request.POST.get('battery', '').encode('utf-8')
    uptime = request.POST.get('uptime', '').encode('utf-8')
    memory = request.POST.get('memory', '').encode('utf-8')
    storage = request.POST.get('storage', '').encode('utf-8')
    wifistrength = request.POST.get('wifistrength', '').encode('utf-8')
    fmver = request.POST.get('fmver', '').encode('utf-8')
    devtype = request.POST.get('devtype', '').encode('utf-8')

    if MDM_POST_DEBUG:
        print "macaddr is", macaddr
        print "battery is", battery
        print "uptime is", uptime
        print "memory is", memory
        print "storage is", storage
        print "wifistrength is", wifistrength
        print "fmver is", fmver
        print "devtype is", devtype

    if not macaddr_check(macaddr):
        return False, "mac address '%s' is incorrect" % macaddr

    #do not check battery
    #if not battery_check(battery):
    #    return False, "battery '%s' is incorrect" % battery

    mdm_key = "%s:%s:%s" % (city, jxd, classroom)
    mdm_list_str = r.hget(tdm_redis_key_mdm, mdm_key)
    if mdm_list_str:
        mdm_list = mdm_list_str.split(',')
    else:
        mdm_list = []
    if macaddr not in mdm_list:
        mdm_list.append(macaddr)
        new_mdm_list_str = ','.join(mdm_list)
        r.hset(tdm_redis_key_mdm, mdm_key, new_mdm_list_str)

    alive_name = "%s:%s:%s:%s:%s" % (tdm_redis_key_mdm_item_prefix, city, jxd, classroom, macaddr)
    alive_key = "%s" % (cur_time)
    alive_data = {}
    alive_data['alive'] = 1
    alive_data['battery'] = battery
    alive_data['ipaddr'] = ipaddr
    if uptime:
        alive_data['uptime'] = uptime
    if memory:
        alive_data['memory'] = memory
    if storage:
        alive_data['storage'] = storage
    if wifistrength:
        alive_data['wifistrength'] = wifistrength
    if fmver:
        alive_data['fmver'] = fmver
    if devtype:
        alive_data['devtype'] = devtype

    r.hset(alive_name, alive_key, json.dumps(alive_data))

    if MDM_POST_DEBUG:
        print alive_name, alive_key, json.dumps(alive_data)

    return True, ''


def _mdm_post(request):
    ret = {}
    ret['result'] = 0

    if MDM_POST_DEBUG:
        print request.POST

    #logging.basicConfig(level=logging.INFO,
    #    format='%(asctime)s %(levelname)s %(message)s',
    #    filename='post.log',
    #    filemode='a')

    #connect the redis database
    r = redis.Redis(host=tdm_redis_host, db=tdm_redis_db)

    city = request.POST.get('city', '').encode('utf-8')
    jxd = request.POST.get('school').encode('utf-8')
    classroom = request.POST.get('classroom', '').encode('utf-8')
    client_addr = request.META.get('REMOTE_ADDR', '').encode('utf-8')

    if MDM_POST_DEBUG:
        print "%s=%s" % ("city", city)
        print "%s=%s" % ("jxd", jxd)
        print "%s=%s" % ("classroom", classroom)
        print "%s=%s" % ("client_addr", client_addr)

    #check city is valiable
    if city_exist_check(r, city) == False:
        err_msg = '%s city "%s" is incorrect' % (client_addr, city)
        #logging.error(err_msg)
        ret['err_msg'] = err_msg
        print err_msg
        return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

    #check school is valiable
    if jxd_exist_check(r, city, jxd) == False:
        err_msg = "%s jxd '%s' is incorrect" % (client_addr, jxd)
        #logging.error(err_msg)
        ret['err_msg'] = err_msg
        print err_msg
        return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

    try:
        post_ret, err_msg = mdm_post_to_redis(r, request, client_addr, city, jxd, classroom)
        if not post_ret:
            #logging.error(err_msg)
            ret['err_msg'] = err_msg
            print err_msg
            return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')
        #logging.info("[mdm] %s post is ok" % (client_addr, ))
        print "[mdm] %s post is ok" % (client_addr, )
    except Exception as e:
        err_msg = "[mdm] %s post error: %s" % (client_addr, str(e))
        #logging.error(err_msg)
        ret['err_msg'] = err_msg
        print err_msg
        return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

    if MDM_POST_DEBUG:
        print "done"
    ret['result'] = 1
    return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

def mdm_post(request):
    try:
        return _mdm_post(request)
    except Exception as e:
        err_msg = '(mdm error):%s' % str(e)
        print err_msg
        return HttpResponseServerError(err_msg)

def _acard_post(request):
    ret = {}
    ret['result'] = 0

    if ACARD_POST_DEBUG:
        print '=====POST====='
        print request.POST
        print '=====POST====='

    client_addr = request.META.get('REMOTE_ADDR')
    city = request.POST.get('city')
    venue = request.POST.get('venue')
    ctm = request.POST.get('ctm')
    status = request.POST.get('status')
    cpu = request.POST.get('cpu')
    memory = request.POST.get('memory')
    disk = request.POST.get('disk')
    app_live = request.POST.get('app_live')
    app_ver = request.POST.get('app_ver')
    cli_ver = request.POST.get('cli_ver', '0.0')
    database = request.POST.get('database')
    port_9100 = request.POST.get('port_9100')
    port_3306 = request.POST.get('port_3306')
    master_slaver = request.POST.get('master_slaver', 'False')
    ip_100 = request.POST.get('ip_100', 'False')
    cardreader = json.loads(request.POST.get('cardreader', '[]'))
    class_date = request.POST.get('class_date')
    attend_num = request.POST.get('attend_num')
    attend = request.POST.get('attend', '0')
    noattend = request.POST.get('noattend', '0')
    total = request.POST.get('total', '0')
    ctm_date = request.POST.get('date', '1970-1-1')

    if ACARD_POST_DEBUG:
        print "%s=[%s]" % ("client_addr", client_addr)
        print "%s=[%s]" % ("city", city)
        print "%s=[%s]" % ("venue", venue)
        print "%s=[%s]" % ("ctm", ctm)
        print "%s=[%s]" % ("status", status)
        print "%s=[%s]" % ("cpu", cpu)
        print "%s=[%s]" % ("memory", memory)
        print "%s=[%s]" % ("disk", disk)
        print "%s=[%s]" % ("app_live", app_live)
        print "%s=[%s]" % ("app_ver", app_ver)
        print "%s=[%s]" % ("cli_ver", cli_ver)
        print "%s=[%s]" % ("port_9100", port_9100)
        print "%s=[%s]" % ("port_3306", port_3306)
        print "%s=[%s]" % ('master_slaver', master_slaver)
        print "%s=[%s]" % ("ip_100", ip_100)
        print "%s=[%s]" % ("cardreader", cardreader)
        print "%s=[%s]" % ("class_date", class_date)
        print "%s=[%s]" % ("ctm_date", ctm_date)
        print "%s=[%s]" % ("attend_num", attend_num)
        print "%s=[%s]" % ("attend", attend)
        print "%s=[%s]" % ("noattend", noattend)
        print "%s=[%s]" % ("toattend", total)
        for cr_ip, cr_ret in cardreader:
            print 'cardreader: %s = %s' % (cr_ip, cr_ret)

    # check data is valid
    all_data = (city, venue, ctm, status, cpu, memory, disk, app_live, app_ver, cli_ver, port_9100, port_3306, ip_100, class_date, ctm_date, attend_num)
    if None in all_data:
        ret['err_msg'] = "data is invalid: %s" % (all_data, )
        print ret['err_msg']
        return HttpResponseBadRequest(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

    #if ACARD_POST_DEBUG:
    #    print all_data

    #connect the redis database
    tmm.db_connect(tdm_mongo_acard_db)

    # find the obj
    ctm_obj = tmm.CtmDevice.objects(devid=ctm).first()
    venue_obj = tmm.Venue.objects(venue_id=venue).first()
    city_obj = tmm.City.objects(zipcode=city).first()

    #if ACARD_POST_DEBUG:
    #    print ctm_obj, venue_obj, city_obj

    if None in (city_obj, venue_obj, ctm_obj):
        ret['err_msg'] = "data obj is invalid"
        print ret['err_msg'], 'city:%s,venue:%s,ctm:%s' %(city_obj, venue_obj, ctm_obj)
        return HttpResponseBadRequest(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

    # save to mongo
    vsl = tmm.AcardCtmLog(
                city = city_obj,
                venue = venue_obj,
                ctm = ctm_obj,
                status = status,
                cpu = cpu,
                memory = memory,
                disk = disk,
                app_live = app_live,
                app_ver = app_ver,
                cli_ver = cli_ver,
                port_9100 = port_9100 == 'True' and True or False,
                port_3306 = port_3306 == 'True' and True or False,
                master_slaver = master_slaver == 'True' and True or False,
                ip_100 = ip_100 == 'True' and True or False,
                crstatus = [],
                class_date = datetime.fromtimestamp(float(class_date)),
                ctm_date = ctm_date,
                attend_num = attend_num,
                attend = int(attend),
                noattend = int(noattend),
                toattend = int(total),
                log_tm = datetime.now())
    for cr_ip, cr_ret in cardreader:
        cas = tmm.CardReaderStatus(ip=cr_ip, status=cr_ret)
        vsl.crstatus.append(cas)
    vsl.save()

    # 将中控机的最新监控记录保存到redis，并设置时限为10分钟后自动删除
    r = redis.Redis(host=tdm_redis_host, db=tdm_redis_db)
    '''
    city:venue:ctmdev:date = '{
            "_id": {"$oid": "5588f44581a6250c922532c0"},
            "city": {"$oid": "5583a9ae81a6253b2a4350cd"},
            "venue": {"$oid": "5583a9ae81a6253b2a4350d3"},
            "ctm": {"$oid": "5583aaf181a6253b931c8d21"},
            "status": true,
            "cpu": 0.0,
            "memory": 15.55,
            "disk": 1.25,
            "app_live": true,
            "app_ver": "V1.0.0",
            "port_9100": true,
            "port_3306": true,
            "ip_100": true,
            "crstatus": [{"ip": "192.168.13.101", "status": true}, {"ip": "192.168.13.102", "status": true}],
            "class_date": {"$date": 1435067598550},
            "attend_num": 256}'
    '''
    key = '%s:%s:%s:%s' % (redis_venue_sync_log_prefix, city_obj.name, venue_obj.name, ctm_obj.devid)
    AcardCtmLog_mongo_to_redis(r, vsl, key, redis_venue_sync_log_ex)
    ret['result'] = 1
    ret['cmd'] = AcardGetAutoCommand(r, city_obj.name, venue_obj.name, ctm_obj.devid)
    #os.system('del "D:\Program Files (x86)\Attend\AttendManage\CardZip\*"')
    if ACARD_POST_DEBUG:
        print ret
    return HttpResponse(json.dumps(ret, ensure_ascii=False), content_type='application/javascript')

def acard_post(request):
    try:
        return _acard_post(request)
    except Exception as e:
        err_msg = '(acard error): %s' % (str(e))
        print err_msg
        return HttpResponseServerError(err_msg)
